#include "EstadoDePreparacionDePartida.h"
#include <list>
#include <map>
#include "Dado.h"
#include "TiradorDeDadosDesdeArchivo.h"
#include <iostream>
using namespace std;

EstadoDePreparacionDePartida::EstadoDePreparacionDePartida(JuegoServerImp* juego) {
	this->juego = juego;
}
	
void EstadoDePreparacionDePartida::asignarEjercitos() {
	unsigned int ejercitosPorJugador;
	switch(juego->getCantidadDeJugadores()) {
		case 2 : ejercitosPorJugador = 40; break;
		case 3 : ejercitosPorJugador = 35; break;
		case 4 : ejercitosPorJugador = 30; break;
		case 5 : ejercitosPorJugador = 25; break;
		case 6 : ejercitosPorJugador = 20; break;
	}
	
	for (int i = 0; i < juego->getCantidadDeJugadores(); i++)
		juego->getJugadores()->at(i)->asignarEjercitos(ejercitosPorJugador);
	sortearTurnos();
}

void EstadoDePreparacionDePartida::sortearTurnos() {
	int mayorValor = 0;
	bool hayUnMayor = false;
	Dado dado;
	multimap<int,int> tiradas;
	for (int i = 0; i < juego->getCantidadDeJugadores(); i++) {
		dado = juego->getTiradorDeDados()->tirar();
		tiradas.insert(pair<int,int>(dado.getValor(),i));
		if (dado.getValor() > mayorValor)
			mayorValor = dado.getValor();
	}
	if (tiradas.count(mayorValor) == 1)
		hayUnMayor=true;
	while (!hayUnMayor) {
		pair<multimap<int,int>::iterator,multimap<int,int>::iterator> rango = tiradas.equal_range(mayorValor);
		multimap<int,int> desempate(rango.first,rango.second);
		tiradas.clear();
		mayorValor = 0;
		for (multimap<int,int>::iterator it = desempate.begin(); it != desempate.end(); ++it) {
			dado = juego->getTiradorDeDados()->tirar();
			tiradas.insert(pair<int,int>(dado.getValor(),it->second));
			if (dado.getValor() > mayorValor)
				mayorValor = dado.getValor();
		}
		if (tiradas.count(mayorValor) == 1)
			hayUnMayor=true;
	}
	vector<Jugador*>* jugadores = juego->getJugadores();
	Jugador* aux = jugadores->at(tiradas.find(mayorValor)->second);
	jugadores->erase(jugadores->begin()+tiradas.find(mayorValor)->second);
	jugadores->insert(jugadores->begin()+tiradas.find(mayorValor)->second,jugadores->at(0));
	jugadores->insert(jugadores->begin(),aux);
}
//TODO: VER ARROJAR EXCEPCIONES
void EstadoDePreparacionDePartida::colocarEjercitos(Jugador* jugador, Territorio* territorio, unsigned int cantidadDeEjercitos) {
	if (jugador->getCantidadDeEjercitos() >= cantidadDeEjercitos)
		if (territorio->getCantidadDeEjercitos() == 0) {
			jugador->quitarEjercitos(cantidadDeEjercitos);
			territorio->colocarEjercitos(cantidadDeEjercitos,jugador->getColor());
		}
		else if (territorio->getEnPoderDe() == jugador->getColor()) {
			if (juego->getMapa()->todosLosTerritoriosConEjercitos()) {
				territorio->colocarEjercitos(cantidadDeEjercitos,jugador->getColor());
				jugador->quitarEjercitos(cantidadDeEjercitos);
			}
			else
				;//throw new Exception("todavia hay territorios vacios por ocupar");
		}
		else
			;//throw new Exception("el territorio esta en poder de territorio->getEnPoderDe()");
	bool todosLosEjercitosUbicados = true;
	for (vector<Jugador*>::iterator it = juego->getJugadores()->begin(); it != juego->getJugadores()->end(); ++it)
		if ((*it)->getCantidadDeEjercitos() != 0) {
			todosLosEjercitosUbicados = false;
			break;
		}
	if (todosLosEjercitosUbicados) {
		juego->setTurno(0);
		juego->setEstado(juego->getEstadoDeRealizacionDePartida());
		juego->getEstadoDeRealizacionDePartida()->reforzarEjercitos(juego->getJugadorEnTurno());
	}
	else
		juego->pasarAlSiguienteTurno();
		
}

void EstadoDePreparacionDePartida::unirse(Jugador* jugador) {
	std::cerr<<"Esta accion no es valida para este estado"<<std::endl;
}

void EstadoDePreparacionDePartida::reforzarEjercitos(Jugador* jugador) {
	std::cerr<<"Esta accion no es valida para este estado"<<std::endl;
}

void EstadoDePreparacionDePartida::realizarAtaque(Ataque* ataque) {
	std::cerr<<"Esta accion no es valida para este estado"<<std::endl;
}

void EstadoDePreparacionDePartida::moverEjercitos(Jugador* jugador, Territorio* origen, Territorio* destino, unsigned int cantidadDeEjercitos) {
	std::cerr<<"Esta accion no es valida para este estado"<<std::endl;
}


EstadoDePreparacionDePartida::~EstadoDePreparacionDePartida()
{
}
